package com.gigalaxy.components
{
	import com.gigalaxy.flex.components.GGSprite;

	import flash.display.Bitmap;
	import flash.display.BitmapData;
	import flash.display.Sprite;
	import flash.events.Event;
	import flash.geom.Matrix;
	import flash.geom.Point;
	import flash.geom.Rectangle;
	import flash.text.TextField;
	import flash.text.TextFormat;
	import flash.text.TextFormatAlign;
	import flash.utils.getTimer;

	public class Count extends GGSprite
	{
		[Embed(source = "assets/CountDownAssets.png")]
		private static const CountDownAssets:Class;
		public static const COUNT_DOWN_ASSETS:Bitmap = new CountDownAssets as Bitmap;

		public static var isCountDown:Boolean = true;
		private static var stepsPerSecond:uint;
		private static var msPerStep:uint;

		private static var inited:Boolean;
		private static var WIDTH:Number;
		private static var HEIGHT:Number;
		private static var X_OFFSET:Number;
		private static var Y_OFFSET:Number;
		private static var anchor:Point;
		private static var canvas:BitmapData;

		/**
		 * viền bao được tính sẵn để giảm công tính toán
		 */
		private static var bound:Vector.<Point>;

		private var countDownDisplay:TextField;
		private var fillUp:Sprite;
		private var cropRect:Rectangle;
		private var matrix:Matrix;
		private var _currentCount:int;
		private var _totalCount:int;
		private var _currentTime:int;
		private var _deltaTime:int;
		private var _previousTime:int;
		private var _currentStep:uint;
		private var _onComplete:Function;

		public function Count()
		{
			initStaticData();
			initData();

			super();
		}

		private function initData():void
		{
			cropRect = new Rectangle(0, 0, WIDTH, HEIGHT);

			canvas.lock();
			cropRect.x = 0;
			canvas.fillRect(cropRect, 0x00631987); // clear
			canvas.copyPixels(COUNT_DOWN_ASSETS.bitmapData, cropRect, anchor);
			canvas.unlock();
		}

		private function initStaticData():void
		{
			if (!inited)
			{
				inited = true;
				WIDTH = 64;
				X_OFFSET = -WIDTH >> 1;
				HEIGHT = 64;
				Y_OFFSET = -HEIGHT >> 1;
				stepsPerSecond = 10;
				msPerStep = 1000 / stepsPerSecond;
				anchor = new Point();

				canvas = new BitmapData(WIDTH, HEIGHT);

				bound = new Vector.<Point>(4, true);
				bound[0] = new Point(32, -16);
				bound[1] = new Point(80, 32);
				bound[2] = new Point(32, 80);
				bound[3] = new Point(-16, 32);
			}
		}

		public function countDown(count:uint, onComplete:Function = null):void
		{
			// force call previous complete callback
			if (_onComplete != null)
			{
				_onComplete.call();
			}

			resetData();

			visible = true;

			_totalCount = count;
			currentCount = 0;

			if (onComplete != null)
			{
				_onComplete = onComplete;
			}

			addEventListener(Event.ENTER_FRAME, drawFillUp, false, 0, true);
		}

		protected function drawFillUp(event:Event):void
		{
			_currentTime = getTimer();
			_deltaTime += _currentTime - _previousTime;

			if (_previousTime > 0 && _deltaTime > msPerStep)
			{
				_deltaTime %= msPerStep;

				fillUp.graphics.clear();

				if (_currentStep == stepsPerSecond) // finish one count
				{
					_currentStep = 1;

					currentCount++;

					if (_currentCount == _totalCount) // finish all count
					{
						visible = false;

						/* không cần thiết nếu visible = false
						fillUp.graphics.beginBitmapFill(canvasBuffer, null, false, true);
						fillUp.graphics.drawRect(0, 0, WIDTH, HEIGHT);
						fillUp.graphics.endFill();
						//*/

						removeEventListener(Event.ENTER_FRAME, drawFillUp);

						if (_onComplete != null)
						{
							_onComplete.call();
						}

						return; // không thực hiện vẽ fill up nữa
					}
				}

				fillUp.graphics.beginBitmapFill(canvasBuffer, null, false, true);
				//fillUp.graphics.lineStyle(1);
				fillUp.graphics.moveTo(32, 32);

				var angle:int = 360 / (_totalCount * stepsPerSecond) * (_currentCount * stepsPerSecond + _currentStep);
				var xPos:int;
				var yPos:int;

				/* realtime compute
				for (var i:uint = 0; i < angle; i += 90) // không có dấu =
				{
					xPos = 48 * Math.cos((i - 90) / 180 * Math.PI) + 32;
					yPos = 48 * Math.sin((i - 90) / 180 * Math.PI) + 32;
					fillUp.graphics.lineTo(xPos, yPos);
				}
				//*/

				//* pre compute
				var numLoop:int = angle / 90;

				for (var i:uint = 0; i <= numLoop; i++) // có dấu =
				{
					xPos = bound[i].x;
					yPos = bound[i].y;
					fillUp.graphics.lineTo(xPos, yPos);
				}
				//*/

				xPos = 48 * Math.cos((angle - 90) * Math.PI / 180) + 32;
				yPos = 48 * Math.sin((angle - 90) * Math.PI / 180) + 32;
				fillUp.graphics.lineTo(xPos, yPos);

				fillUp.graphics.lineTo(32, 32);
				fillUp.graphics.endFill();

				_currentStep++;
			}

			_previousTime = _currentTime;
		}

		override protected function createChildren():void
		{
			super.createChildren();

			canvasBuffer = new BitmapData(WIDTH, HEIGHT);
			matrix = new Matrix();
			matrix.translate(X_OFFSET, Y_OFFSET);

			if (!countDownDisplay)
			{
				createCountDownDisplay();
			}

			if (!fillUp)
			{
				createFillOut();
			}

			updateDisplayList();
		}

		override protected function drawBackground():void
		{
			super.drawBackground();

			graphics.beginBitmapFill(canvas, matrix, false, true);
			graphics.drawRect(X_OFFSET, Y_OFFSET, WIDTH, HEIGHT);
			graphics.endFill();
		}


		private function createFillOut():void
		{
			fillUp = new Sprite();

			//*
			canvasBuffer.lock();
			cropRect.x = 0;
			canvasBuffer.fillRect(cropRect, 0x00631987); // clear
			cropRect.x = 64;
			canvasBuffer.copyPixels(COUNT_DOWN_ASSETS.bitmapData, cropRect, anchor);
			canvasBuffer.unlock();
			//*/

			fillUp.x = X_OFFSET;
			fillUp.y = Y_OFFSET;

			addChild(fillUp);
		}

		private function createCountDownDisplay():void
		{
			var format:TextFormat = new TextFormat();
			format.color = 0xFFFFFF;
			format.font = "_typewriter";
			format.bold = true;
			format.size = 15;
			format.align = TextFormatAlign.CENTER;

			countDownDisplay = new TextField();
			countDownDisplay.selectable = false;
			countDownDisplay.multiline = false;
			countDownDisplay.wordWrap = false;
			countDownDisplay.defaultTextFormat = format;
			countDownDisplay.width = 32;
			countDownDisplay.x = 16 + X_OFFSET;
			countDownDisplay.y = 22 + Y_OFFSET;

			addChild(countDownDisplay);
		}

		override public function resetData():void
		{
			super.resetData();

			visible = false;

			_currentCount = -1; // set = -1 để current count = 0 có hiệu lực!!!
			_totalCount = 0;
			_currentStep = 1;
			_currentTime = 0;
			_deltaTime = 0;
			_previousTime = 0;

			_onComplete = null;

			if (hasEventListener(Event.ENTER_FRAME))
			{
				removeEventListener(Event.ENTER_FRAME, drawFillUp);
			}
		}

		public function get currentCount():int
		{
			return _currentCount;
		}

		public function set currentCount(value:int):void
		{
			if (_currentCount != value)
			{
				_currentCount = value;

				if (isCountDown)
				{
					countDownDisplay.text = (_totalCount - value).toString();
				}
				else
				{
					countDownDisplay.text = value.toString();
				}
			}
		}
	}
}
